﻿
#ifndef _NET_MESSAGE_DEFINE_H_
#define _NET_MESSAGE_DEFINE_H_

#ifdef _WIN32
#pragma warning(disable:4200) // 使用了非标准扩展: 结构/联合中的零大小数组
#endif

#include <stdlib.h>
#include <string.h>
#include <assert.h>

#ifdef __cplusplus
extern "C" {
#endif

#include <MyPshPack1.h>

typedef enum {
    MessageType_Unknown = 0, 
    
    // 文本消息
    MessageType_TextMessage,

    // 新用户连接
    MessageType_NewUserIn,

    // 某客户端广播文本消息
    MessageType_BroadTextMessageToOther,




    // 通用消息返回, 一般是客户端得到的来自服务器的消息
    MessageType_GeneralResponse = 20000,
}MessageType;

typedef struct {
    // 本次消息的总长度
    int dataLength; 
    // 本次消息的类型
    MessageType type;
    //char data[0];
}DataHead;

typedef struct {
    DataHead head;
    // 文本消息的字节长度，该长度不包含下面msg成员的1字节，但文本消息以'\0'结尾
    int len;   
    char msg[1];
}TextMessage;


#include <MyPopPack.h>
#ifdef __cplusplus
}
#endif

#include <string>

class MessageBuildHelper
{
public:

    void freeResource(void* ptr) {
        if (ptr) {
            if (ptr) free(ptr);
        }
    }

    // 获取消息长度，已处理网络字节序
    int getMessageLength(const DataHead *msgHead) {
        if (!msgHead) return -1;
        u_long l = ntohl((u_long)msgHead->dataLength);
        return (int)l;
    }

    void setMessageLength(DataHead *msgHead, int length) {
        if (msgHead) {
            msgHead->dataLength = (int)htonl((u_long)length);
        }
    }

    MessageType getMessageType(const DataHead *msgHead) {
        MessageType mt = MessageType::MessageType_Unknown;
        if (!msgHead) return mt;
        u_long t = ntohl((u_long)msgHead->type);
        return (MessageType)t;
    }

    void setMessageType(DataHead *msgHead, MessageType type) {
        if (msgHead) {
            msgHead->type = (MessageType)htonl((u_long)type);
        }
    }



    // ----------------------------------------------------------------------
    // 


    TextMessage* buildTextMessage(const char* message) {
        TextMessage *msg = NULL;
        int len = 0, lenTxt = 0;
        //int copyflag = 0;

        do
        {
            if (message == NULL)
                len = sizeof(TextMessage);
            else {
                lenTxt = (int)strlen(message);
                //if (lenTxt > 0) copyflag = 1;
                len = lenTxt + sizeof(TextMessage);
            }
            
            msg = (TextMessage*)malloc(len);
            if (msg == NULL) {
                // 设置一些错误值
                break;
            }
            memset(msg, 0, len);

            setMessageLength(&msg->head, len);
            setMessageType(&msg->head, MessageType::MessageType_TextMessage);
            
            msg->len = htonl(lenTxt);
            strcpy(msg->msg, message);
            
        } while (false);

        return msg;
    }

    int parseTextMessage(const DataHead *msgHead, std::string& str) {
        int retval = -1;

        do
        {
            if (!msgHead) break;
            MessageType type = getMessageType(msgHead);
            if (MessageType::MessageType_TextMessage != type)
                break;

            TextMessage* txt = (TextMessage*)msgHead;
            int strLen = ntohl(txt->len);
            assert(strLen >= 0);

            str.assign(txt->msg, strLen);
            retval = 0;
        } while (false);

        return retval;
    }
};

#endif // !_NET_MESSAGE_DEFINE_H_
